package com.freemalll.auth.cloud.business.common;


import lombok.Getter;
import org.apache.commons.collections4.map.LinkedMap;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import com.freemalll.auth.cloud.business.common.Enumeration;

/**
 * 自动扫描 {@link com.freemalll.system.common.Enumeration} 注解,自动注册
 *
 * @author wangw
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
 * @see com.freemalll.system.common.Enumeration
 */
public class CommonEnum {

    /**
     * 全量枚举Map集合
     */
    public static Map<String, Class> enumsMap = new HashMap<>();
    /**
     * 全量枚举List集合
     * -- GETTER --
     * 获取全量枚举List集合
     *
     * @return
     */
    @Getter
    public static List<CommonEnumDto> enumsList = new ArrayList<>();

    static {
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AnnotationTypeFilter(Enumeration.class));
        Set<BeanDefinition> candidateComponents = provider.findCandidateComponents("com.freemalll.auth");
        ClassLoader classLoader = provider.getResourceLoader().getClassLoader();
        for (BeanDefinition candidateComponent : candidateComponents) {
            if (candidateComponent instanceof AnnotatedBeanDefinition) {
                String beanClassName = candidateComponent.getBeanClassName();
                AnnotationMetadata metadata = ((AnnotatedBeanDefinition) candidateComponent).getMetadata();
                AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(Enumeration.class.getName()));
                Assert.state(attributes != null, "注解系统出错");
                Class<?> enumeration = ClassUtils.resolveClassName(beanClassName, classLoader);

                String id = attributes.getString("id");
                if (!StringUtils.hasLength(id) || Constant.DEFAULT_NONE.equals(id)) {
                    id = StringUtils.uncapitalize(enumeration.getSimpleName());
                    if (id.endsWith("Enum")) {
                        id = id.substring(0, id.length() - 4); // 除去Enum
                    }
                }
                addEnumToCollect(id,
                        attributes.getString("description"), enumeration);
            }
        }
    }

    /**
     * 将枚举添加到Map和List集合里
     *
     * @param code
     * @param codeName
     * @param clz
     */
    public static void addEnumToCollect(String code, String codeName, Class clz) {
        enumsMap.put(code, clz);
        CommonEnumDto appEnumDto = new CommonEnumDto();
        appEnumDto.setCode(code);
        appEnumDto.setCodeName(codeName);
        appEnumDto.setChildren(enumDtoList(clz));
        enumsList.add(appEnumDto);
    }

    /**
     * 获取全量枚举Map集合
     *
     * @return
     */
    public static Map<String, Map<String, String>> getEnumsMap() {
        Map<String, Map<String, String>> result = new HashMap<>();
        for (Map.Entry<String, Class> key : CommonEnum.enumsMap.entrySet()) {
            Map<String, String> clzResult = new LinkedMap();
            for (Object clz : key.getValue().getEnumConstants()) {
                if (clz instanceof Enumerable) {
                    clzResult.put(clz.toString(), ((Enumerable) clz).getDescription());
                }
            }
            result.put(key.getKey(), clzResult);
        }
        return result;
    }

    /**
     * 将枚举转化成DTO
     *
     * @param clz
     * @return
     */
    public static List<CommonEnumDto> enumDtoList(Class clz) {
        List<CommonEnumDto> appEnumDtos = new ArrayList<>();
        for (Object obj : clz.getEnumConstants()) {
            CommonEnumDto appEnumDto = new CommonEnumDto();
            if (obj instanceof Enumerable) {
                Enumerable<?> enumerable = (Enumerable<?>) obj;
                appEnumDto.setCode(enumerable.getValue());
                appEnumDto.setCodeName(enumerable.getDescription());
            }
            appEnumDtos.add(appEnumDto);
        }
        return appEnumDtos;
    }


    /***************************业务类型begin***************************************/

    /**
     * 支持场景
     */
//    @Enumeration
//    public enum MenuType implements Enumerable<String> {
//        MENU("菜单"),
//        PAGE("页面"),
//        BUTTON("按钮"),
//        FUNCTION("功能");
//
//        private final String desc;
//
//        MenuType(String desc) {
//            this.desc = desc;
//        }
//
//        @Override
//        public String getDescription() {
//            return desc;
//        }
//    }


}
